package com.lagou.handler;

import com.lagou.helper.ApplicationContextGetBeanHelper;
import com.lagou.helper.Singleton;
import com.lagou.protocol.RpcRequest;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.retry.RetryNTimes;
import org.apache.zookeeper.CreateMode;

import java.lang.reflect.Method;
import java.net.SocketAddress;
import java.util.Map;
import java.util.Random;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;

public class RpcRequestHandler extends SimpleChannelInboundHandler<RpcRequest>{

    CuratorFramework client = null;
    Random random = new Random();

    private static final String RESP_SEQ = "/RESP_SEQ";



    @Override
    protected void channelRead0(ChannelHandlerContext ctx, RpcRequest rpcRequest) throws Exception {
        if (client == null){
            client = CuratorFrameworkFactory.newClient("127.0.0.1:2181", new RetryNTimes(3, 1000));
            client.start();

            if (client.checkExists().forPath(RESP_SEQ) == null) {
                client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath(RESP_SEQ);
            }

        }

        // 1. 根据RpcRequest获取对应的类
        Object obj = ApplicationContextGetBeanHelper.getBean(rpcRequest.getClassName());
        Class<?> aClass = obj.getClass();

        // 打印对应的端口
        Channel channel = ctx.channel();
        SocketAddress localAddress = channel.localAddress();
        String ipPort = localAddress.toString();
        System.out.print(ipPort+"------>");
        Singleton.put(ipPort);

        // 2.在使用动态代理调用对应的方法
        Method method = aClass.getMethod(rpcRequest.getMethodName(), rpcRequest.getParameterTypes());
        Object invoke = method.invoke(obj, rpcRequest.getParameters());

        // 这里获取一个0～5的随机变量，表示接口的响应时间，然后存到zk中
        Integer seq = random.nextInt(5);


        if (client.checkExists().forPath(RESP_SEQ+ipPort) == null) {
            client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath(RESP_SEQ+ipPort, (seq+"").getBytes());
        }else {
            client.setData().forPath(RESP_SEQ+ipPort, (seq+"").getBytes());
        }


        // 3.把调用实现类的方法获得的结果写到客户端
        ctx.writeAndFlush(invoke.toString());

        new Thread(() -> {
            try {
                TimeUnit.MILLISECONDS.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (System.currentTimeMillis() - Singleton.get(ipPort)  > 5000){
                System.out.println("------------------");
                try {
                    if (client.checkExists().forPath(RESP_SEQ+ipPort) == null) {
                        client.delete().forPath(RESP_SEQ+ipPort);
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        },"线程1").start();
    }



}

